home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  39.6 KB  |  1,447 lines

  1. /* draw.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: draw.c,v 1.40 1995/11/22 13:36:18 brianp Exp $
  26.  
  27. $Log: draw.c,v $
  28.  * Revision 1.40  1995/11/22  13:36:18  brianp
  29.  * small optimization to VB.Win[][] computation
  30.  *
  31.  * Revision 1.39  1995/11/03  22:35:08  brianp
  32.  * call new vertex fogging functions
  33.  *
  34.  * Revision 1.38  1995/11/03  17:40:52  brianp
  35.  * removed unused variables
  36.  *
  37.  * Revision 1.37  1995/11/01  21:45:26  brianp
  38.  * use new gl_color_shade_vertices() function
  39.  *
  40.  * Revision 1.36  1995/10/27  21:37:44  brianp
  41.  * implemented glPolygonOffsetEXT
  42.  * optimized computation of CC.Plane[ABCD]
  43.  *
  44.  * Revision 1.35  1995/10/19  15:47:00  brianp
  45.  * added gamma support
  46.  *
  47.  * Revision 1.34  1995/10/17  21:42:55  brianp
  48.  * enabled VB.MonoColor logic
  49.  *
  50.  * Revision 1.33  1995/09/28  19:40:02  brianp
  51.  * replaced ClipFlag[] with Unclipped[]
  52.  *
  53.  * Revision 1.32  1995/09/27  18:33:24  brianp
  54.  * added call to new gl_transform_normals function
  55.  *
  56.  * Revision 1.31  1995/09/26  16:04:55  brianp
  57.  * moved transform_points to xform.c
  58.  *
  59.  * Revision 1.30  1995/09/25  19:23:40  brianp
  60.  * implemented per-vertex glMaterial calls
  61.  *
  62.  * Revision 1.29  1995/09/22  22:12:41  brianp
  63.  * optimized the xform_vb function to unroll loops, use maximum registers
  64.  *
  65.  * Revision 1.28  1995/09/22  16:51:16  brianp
  66.  * fixed Anyclipped typo
  67.  *
  68.  * Revision 1.27  1995/09/22  16:49:42  brianp
  69.  * added VB.AnyClipped logic
  70.  * added conditionals to gl_execute_vertex
  71.  * prototyped VB.MonoColor logic
  72.  *
  73.  * Revision 1.26  1995/09/17  19:31:03  brianp
  74.  * better logic for computing plane eq of polygons, accidental culling fixed
  75.  *
  76.  * Revision 1.25  1995/09/15  18:39:43  brianp
  77.  * complete restructuring to "vectorize" the vertex pipeline
  78.  *
  79.  * Revision 1.24  1995/07/28  21:33:21  brianp
  80.  * code cleanup, adapt gl_index_shade calls for GLfloat result
  81.  *
  82.  * Revision 1.23  1995/06/20  16:29:36  brianp
  83.  * don't scale Z to integer values here
  84.  * introduced new triangle, polygon area code but not used yet
  85.  *
  86.  * Revision 1.22  1995/06/02  18:59:31  brianp
  87.  * added special case for computing plane equation of 3-sided polygon
  88.  *
  89.  * Revision 1.21  1995/06/02  13:55:09  brianp
  90.  * implemented vertex/primitive buffering
  91.  *
  92.  * Revision 1.20  1995/05/26  19:32:02  brianp
  93.  * replace many assignments in gl_color() with macros
  94.  *
  95.  * Revision 1.19  1995/05/22  21:02:41  brianp
  96.  * Release 1.2
  97.  *
  98.  * Revision 1.18  1995/05/22  21:00:36  brianp
  99.  * tried initial vertex buffering
  100.  *
  101.  * Revision 1.17  1995/05/17  13:17:22  brianp
  102.  * changed default CC.Mode value to allow use of real OpenGL headers
  103.  * removed need for CC.MajorMode variable
  104.  *
  105.  * Revision 1.16  1995/05/15  16:07:33  brianp
  106.  * moved StippleCounter init to new place
  107.  *
  108.  * Revision 1.15  1995/05/12  16:29:18  brianp
  109.  * added #define for NULL
  110.  *
  111.  * Revision 1.14  1995/03/27  20:31:26  brianp
  112.  * new Texture.Enabled scheme
  113.  *
  114.  * Revision 1.13  1995/03/24  15:31:23  brianp
  115.  * introduced VB
  116.  *
  117.  * Revision 1.12  1995/03/23  17:10:12  brianp
  118.  * changed render_point() to render_points(n)
  119.  *
  120.  * Revision 1.11  1995/03/09  21:42:09  brianp
  121.  * new ModelViewInv matrix logic
  122.  *
  123.  * Revision 1.10  1995/03/09  20:08:04  brianp
  124.  * introduced TRANSFORM_POINT and TRANSFORM_NORMAL macros
  125.  *
  126.  * Revision 1.9  1995/03/04  19:29:44  brianp
  127.  * 1.1 beta revision
  128.  *
  129.  * Revision 1.8  1995/03/02  19:10:00  brianp
  130.  * fixed a texgen bug
  131.  *
  132.  * Revision 1.7  1995/02/27  22:48:48  brianp
  133.  * modified for PB
  134.  *
  135.  * Revision 1.6  1995/02/27  15:08:04  brianp
  136.  * added Vcolor/Vindex scheme
  137.  *
  138.  * Revision 1.5  1995/02/26  22:58:43  brianp
  139.  * more zero-area polygon work
  140.  *
  141.  * Revision 1.4  1995/02/26  21:59:43  brianp
  142.  * *** empty log message ***
  143.  *
  144.  * Revision 1.3  1995/02/25  22:07:56  brianp
  145.  * relaxed test for zero-area polygons, still not perfect though
  146.  *
  147.  * Revision 1.2  1995/02/24  15:23:36  brianp
  148.  * removed initialization of d from render_point()
  149.  * added RasterColor code to gl_rasterpos()
  150.  *
  151.  * Revision 1.1  1995/02/24  14:20:43  brianp
  152.  * Initial revision
  153.  *
  154.  */
  155.  
  156.  
  157. /*
  158.  * Draw points, lines, and polygons.
  159.  */
  160.  
  161.  
  162. #ifdef DEBUG
  163. #  include <assert.h>
  164. #endif
  165. #include <math.h>
  166. #include <stdio.h>
  167. #include <stdlib.h>
  168. #include <string.h>
  169. #include "clip.h"
  170. #include "context.h"
  171. #include "dd.h"
  172. #include "draw.h"
  173. #include "feedback.h"
  174. #include "fog.h"
  175. #include "gamma.h"
  176. #include "light.h"
  177. #include "lines.h"
  178. #include "list.h"
  179. #include "macros.h"
  180. #include "pb.h"
  181. #include "points.h"
  182. #include "polygons.h"
  183. #include "texture.h"
  184. #include "vb.h"
  185. #include "xform.h"
  186.  
  187. /*#include "triangle.h"*/
  188.  
  189.  
  190.  
  191. #ifndef NULL
  192. #  define NULL 0
  193. #endif
  194.  
  195.  
  196. #ifdef DEBUG
  197. #  define ASSERT(X)   assert(X)
  198. #else
  199. #  define ASSERT(X)
  200. #endif
  201.  
  202.  
  203.  
  204. /*
  205.  * Check if the global material has to be updated with info that was
  206.  * associated with a vertex via glMaterial.
  207.  */
  208. static void update_material( GLuint i )
  209. {
  210.    if (VB.MaterialMask[i]) {
  211.       if (VB.MaterialMask[i] & FRONT_AMBIENT_BIT) {
  212.          COPY_4V( CC.Light.Material[0].Ambient, VB.Material[i][0].Ambient );
  213.       }
  214.       if (VB.MaterialMask[i] & BACK_AMBIENT_BIT) {
  215.          COPY_4V( CC.Light.Material[1].Ambient, VB.Material[i][1].Ambient );
  216.       }
  217.       if (VB.MaterialMask[i] & FRONT_DIFFUSE_BIT) {
  218.          COPY_4V( CC.Light.Material[0].Diffuse, VB.Material[i][0].Diffuse );
  219.       }
  220.       if (VB.MaterialMask[i] & BACK_DIFFUSE_BIT) {
  221.          COPY_4V( CC.Light.Material[1].Diffuse, VB.Material[i][1].Diffuse );
  222.       }
  223.       if (VB.MaterialMask[i] & FRONT_SPECULAR_BIT) {
  224.          COPY_4V( CC.Light.Material[0].Specular, VB.Material[i][0].Specular );
  225.       }
  226.       if (VB.MaterialMask[i] & BACK_SPECULAR_BIT) {
  227.          COPY_4V( CC.Light.Material[1].Specular, VB.Material[i][1].Specular );
  228.       }
  229.       if (VB.MaterialMask[i] & FRONT_EMISSION_BIT) {
  230.          COPY_4V( CC.Light.Material[0].Emission, VB.Material[i][0].Emission );
  231.       }
  232.       if (VB.MaterialMask[i] & BACK_EMISSION_BIT) {
  233.          COPY_4V( CC.Light.Material[1].Emission, VB.Material[i][1].Emission );
  234.       }
  235.       if (VB.MaterialMask[i] & FRONT_SHININESS_BIT) {
  236.          CC.Light.Material[0].Shininess = VB.Material[i][0].Shininess;
  237.       }
  238.       if (VB.MaterialMask[i] & BACK_SHININESS_BIT) {
  239.          CC.Light.Material[1].Shininess = VB.Material[i][1].Shininess;
  240.       }
  241.       if (VB.MaterialMask[i] & FRONT_INDEXES_BIT) {
  242.          CC.Light.Material[0].AmbientIndex = VB.Material[i][0].AmbientIndex;
  243.          CC.Light.Material[0].DiffuseIndex = VB.Material[i][0].DiffuseIndex;
  244.          CC.Light.Material[0].SpecularIndex = VB.Material[i][0].SpecularIndex;
  245.       }
  246.       if (VB.MaterialMask[i] & BACK_INDEXES_BIT) {
  247.          CC.Light.Material[1].AmbientIndex = VB.Material[i][1].AmbientIndex;
  248.          CC.Light.Material[1].DiffuseIndex = VB.Material[i][1].DiffuseIndex;
  249.          CC.Light.Material[1].SpecularIndex = VB.Material[i][1].SpecularIndex;
  250.       }
  251.       VB.MaterialMask[i] = 0;  /* reset now */
  252.    }
  253. }
  254.  
  255.  
  256.  
  257. /*
  258.  * Render a line segment from VB[v1] to VB[v2] when either one or both
  259.  * endpoints must be clipped.
  260.  */
  261. static void render_clipped_line( GLuint v1, GLuint v2 )
  262. {
  263.    GLfloat d;
  264.    GLfloat ndc_x, ndc_y, ndc_z;
  265.    GLuint provoking_vertex;
  266.  
  267.    /* which vertex dictates the color when flat shading: */
  268.    provoking_vertex = v2;
  269.  
  270.    /*
  271.     * Clipping may introduce new vertices.  New vertices will be stored
  272.     * in the vertex buffer arrays starting with location VB.Free.  After
  273.     * we've rendered the line, these extra vertices can be overwritten.
  274.     */
  275.    VB.Free = VB_MAX;
  276.  
  277.    /* Clip against user clipping planes */
  278.    if (CC.Transform.AnyClip) {
  279.       if (gl_userclip_line( &v1, &v2 )==0)
  280.     return;
  281.    }
  282.  
  283.    /* Apply projection matrix:  clip = Proj * eye */
  284.    TRANSFORM_POINT( VB.Clip[v1], CC.ProjectionMatrix, VB.Eye[v1] );
  285.    TRANSFORM_POINT( VB.Clip[v2], CC.ProjectionMatrix, VB.Eye[v2] );
  286.  
  287.    /* Clip against view volume */
  288.    if (gl_viewclip_line( &v1, &v2 )==0)
  289.       return;
  290.  
  291.    /* Transform from clip coords to ndc:  ndc = clip / W */
  292.    ASSERT( VB.Clip[v1][3] != 0.0 );
  293.    ASSERT( VB.Clip[v2][3] != 0.0 );
  294.    d = 1.0F / VB.Clip[v1][3];
  295.    ndc_x = VB.Clip[v1][0] * d;
  296.    ndc_y = VB.Clip[v1][1] * d;
  297.    ndc_z = VB.Clip[v1][2] * d;
  298.  
  299.    /* Map ndc coord to window coords. */
  300.    VB.Win[v1][0] = MAP_X( ndc_x );
  301.    VB.Win[v1][1] = MAP_Y( ndc_y );
  302.    VB.Win[v1][2] = MAP_Z( ndc_z );
  303.  
  304.    /* Transform from clip coords to ndc:  ndc = clip / W */
  305.    d = 1.0F / VB.Clip[v2][3];
  306.    ndc_x = VB.Clip[v2][0] * d;
  307.    ndc_y = VB.Clip[v2][1] * d;
  308.    ndc_z = VB.Clip[v2][2] * d;
  309.  
  310.    /* Map ndc coord to window coords. */
  311.    VB.Win[v2][0] = MAP_X( ndc_x );
  312.    VB.Win[v2][1] = MAP_Y( ndc_y );
  313.    VB.Win[v2][2] = MAP_Z( ndc_z );
  314.  
  315.    (*CC.LineFunc)( v1, v2, provoking_vertex );
  316. }
  317.  
  318.  
  319.  
  320. #ifdef LEAVEOUT
  321. /*
  322.  * Apply the glPolygonOffsetEXT transformation to the current plane
  323.  * equation.  Basically, we just have to add an offset to the D term.
  324.  */
  325. static void offset_polygon( void )
  326. {
  327.    GLfloat ac, bc, m, offset;
  328.    ac = CC.PlaneA / CC.PlaneC;
  329.    bc = CC.PlaneB / CC.PlaneC;
  330.    if (ac<0.0F)  ac = -ac;
  331.    if (bc<0.0F)  bc = -bc;
  332.    m = MAX2( ac, bc );
  333. /*
  334.    m = sqrt( ac*ac + bc*bc );
  335. */
  336.    offset = m * CC.Polygon.OffsetFactor + CC.Polygon.OffsetBias;
  337.    CC.PlaneD = CC.PlaneD + CC.PlaneC * offset;
  338. }
  339. #endif
  340.  
  341.  
  342. #define OFFSET_POLYGON( A, B, C, D )                    \
  343.     {                                \
  344.        GLfloat m, ac = (A)/(C), bc = (B)/(C);            \
  345.        if (ac<0.0F)  ac = -ac;                    \
  346.        if (bc<0.0F)  bc = -bc;                    \
  347.        m = MAX2( ac, bc );                        \
  348.        D += (C) * (m * CC.Polygon.OffsetFactor + CC.Polygon.OffsetBias); \
  349.     }
  350.  
  351.  
  352.  
  353.  
  354. /*
  355.  * Render a polygon in which at least one vertex has to be clipped.
  356.  * Input:  n - number of vertices
  357.  *         vlist - list of vertices in the polygon.
  358.  *         odd_flag - if non-zero, reverse the orientation of the polygon
  359.  */
  360. static void render_clipped_polygon( GLuint n, GLuint vlist[], GLuint odd_flag )
  361. {
  362.    GLuint i, j;
  363.    GLuint provoking_vertex;
  364.    GLuint facing;
  365.  
  366.    /* which vertex dictates the color when flat shading: */
  367.    provoking_vertex = (CC.Mode==GL_POLYGON) ? vlist[0] : vlist[n-1];
  368.  
  369.    /*
  370.     * Clipping may introduce new vertices.  New vertices will be stored
  371.     * in the vertex buffer arrays starting with location VB.Free.  After
  372.     * we've rendered the polygon, these extra vertices can be overwritten.
  373.     */
  374.    VB.Free = VB_MAX;
  375.  
  376.    /* Clip against user clipping planes in eye coord space. */
  377.    if (CC.Transform.AnyClip) {
  378.       n = gl_userclip_polygon( n, vlist );
  379.       if (n<3)
  380.     return;
  381.    }
  382.  
  383.    /* Transform vertices from eye to clip coordinates:  clip = Proj * eye */
  384.    for (i=0;i<n;i++) {
  385.       j = vlist[i];
  386.       TRANSFORM_POINT( VB.Clip[j], CC.ProjectionMatrix, VB.Eye[j] );
  387.    }
  388.  
  389.    /* Clip against view volume in clip coord space */
  390.    n = gl_viewclip_polygon( n, vlist );
  391.    if (n<3)
  392.      return;
  393.  
  394.    /* Transform vertices from clip to ndc:  ndc = clip / W */
  395.    for (i=0;i<n;i++) {
  396.       GLfloat d, ndc_x, ndc_y, ndc_z;
  397.       j = vlist[i];
  398.       ASSERT( VB.Clip[j][3] != 0.0 );
  399.       d = 1.0F / VB.Clip[j][3];
  400.       ndc_x = VB.Clip[j][0] * d;
  401.       ndc_y = VB.Clip[j][1] * d;
  402.       ndc_z = VB.Clip[j][2] * d;
  403.  
  404.       /* Transform ndc coord to a window coord.  Note that window Z values */
  405.       /* are scaled to integer Z buffer values. */
  406.       VB.Win[j][0] = MAP_X( ndc_x );
  407.       VB.Win[j][1] = MAP_Y( ndc_y );
  408.       VB.Win[j][2] = MAP_Z( ndc_z );
  409.  
  410. #ifdef NEW
  411.       VB.WinX[j] = (GLint) (MAP_X( ndc_x ) * SUB_PIX_SCALE);
  412.       VB.WinY[j] = (GLint) (MAP_Y( ndc_y ) * SUB_PIX_SCALE);
  413.       VB.WinZ[j] = (GLint) (MAP_Z( ndc_z ) * DEPTH_SCALE);
  414. #endif
  415.    }
  416.  
  417.    /* Compute the plane equation of polygon: ax + by + cz = d */
  418.    if (CC.ComputePlane) {
  419.       GLuint j0 = vlist[0];
  420.       GLuint j1 = vlist[1];
  421.       GLuint j2 = vlist[2];
  422.       GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  423.       GLfloat ex = VB.Win[j1][0] - VB.Win[j3][0];
  424.       GLfloat ey = VB.Win[j1][1] - VB.Win[j3][1];
  425.       GLfloat ez = VB.Win[j1][2] - VB.Win[j3][2];
  426.       GLfloat fx = VB.Win[j2][0] - VB.Win[j0][0];
  427.       GLfloat fy = VB.Win[j2][1] - VB.Win[j0][1];
  428.       GLfloat fz = VB.Win[j2][2] - VB.Win[j0][2];
  429.       GLfloat a, b, c, d;
  430.       c = ex*fy-ey*fx;
  431.       if (c==0.0F) {
  432.          /* polygon is perpindicular to view plane, don't draw it */
  433.          return;
  434.       }
  435.  
  436.       /* compute orientation:  0=front, 1=back */
  437.       facing = (c<0.0F) ^ odd_flag ^ (CC.Polygon.FrontFace==GL_CW);
  438.  
  439.       if (CC.Polygon.CullFlag && facing==(CC.Polygon.CullFaceMode==GL_BACK)) {
  440.      return;   /* culled */
  441.       }
  442.       a = ey*fz-ez*fy;
  443.       b = ez*fx-ex*fz;
  444.       d = a*VB.Win[j0][0] + b*VB.Win[j0][1] + c*VB.Win[j0][2];
  445.       if (CC.Polygon.OffsetEnabled) {
  446.          OFFSET_POLYGON( a, b, c, d );
  447.       }
  448.       CC.PlaneA = a;
  449.       CC.PlaneB = b;
  450.       CC.PlaneC = c;
  451.       CC.PlaneD = d;
  452.    }
  453.    else {
  454.       CC.PlaneA = 0.0F;
  455.       CC.PlaneB = 0.0F;
  456.       CC.PlaneC = 1.0F;
  457.       CC.PlaneD = 0.0F;
  458.       facing = 0;
  459.    }
  460.  
  461.    if (facing==1 && CC.Light.Enabled && CC.Light.Model.TwoSide) {
  462.       /* use back color or index */
  463.       VB.Color = VB.Bcolor;
  464.       VB.Index = VB.Bindex;
  465.    }
  466.    else {
  467.       /* use front color or index */
  468.       VB.Color = VB.Fcolor;
  469.       VB.Index = VB.Findex;
  470.    }
  471.  
  472.    (*CC.PolygonFunc)( n, vlist, provoking_vertex );
  473. }
  474.  
  475.  
  476.  
  477. /*
  478.  * Render a polygon in which doesn't have to be clipped.
  479.  * Input:  n - number of vertices
  480.  *         vlist - list of vertices in the polygon.
  481.  *         odd_flag - if non-zero, reverse the orientation of the polygon
  482.  */
  483. static void render_polygon( GLuint n, GLuint vlist[], GLuint odd_flag )
  484. {
  485.    GLuint provoking_vertex;
  486.    GLuint facing;
  487.  
  488.    /* which vertex dictates the color when flat shading: */
  489.    provoking_vertex = (CC.Mode==GL_POLYGON) ? vlist[0] : vlist[n-1];
  490.  
  491.    /* Compute the plane equation of polygon: ax + by + cz = d */
  492.    if (CC.ComputePlane) {
  493.       GLuint j0 = vlist[0];
  494.       GLuint j1 = vlist[1];
  495.       GLuint j2 = vlist[2];
  496.       GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  497.       GLfloat ex = VB.Win[j1][0] - VB.Win[j3][0];
  498.       GLfloat ey = VB.Win[j1][1] - VB.Win[j3][1];
  499.       GLfloat ez = VB.Win[j1][2] - VB.Win[j3][2];
  500.       GLfloat fx = VB.Win[j2][0] - VB.Win[j0][0];
  501.       GLfloat fy = VB.Win[j2][1] - VB.Win[j0][1];
  502.       GLfloat fz = VB.Win[j2][2] - VB.Win[j0][2];
  503.       GLfloat a, b, c, d;
  504.       c = ex*fy-ey*fx;
  505.       if (c==0.0F) {
  506.          /* polygon is perpindicular to view plane, don't draw it */
  507.          return;
  508.       }
  509.  
  510.       /* compute orientation:  0=front, 1=back */
  511.       facing = (c<0.0F) ^ odd_flag ^ (CC.Polygon.FrontFace==GL_CW);
  512.  
  513.       if (CC.Polygon.CullFlag && facing==(CC.Polygon.CullFaceMode==GL_BACK)) {
  514.          return;   /* culled */
  515.       }
  516.       a = ey*fz-ez*fy;
  517.       b = ez*fx-ex*fz;
  518.       d = a*VB.Win[j0][0] + b*VB.Win[j0][1] + c*VB.Win[j0][2];
  519.       if (CC.Polygon.OffsetEnabled) {
  520.          OFFSET_POLYGON( a, b, c, d );
  521.       }
  522.       CC.PlaneA = a;
  523.       CC.PlaneB = b;
  524.       CC.PlaneC = c;
  525.       CC.PlaneD = d;
  526.    }
  527.    else {
  528.       CC.PlaneA = 0.0F;
  529.       CC.PlaneB = 0.0F;
  530.       CC.PlaneC = 1.0F;
  531.       CC.PlaneD = 0.0F;
  532.       facing = 0;
  533.    }
  534.  
  535.    if (facing==1 && CC.Light.Enabled && CC.Light.Model.TwoSide) {
  536.       /* use back color or index */
  537.       VB.Color = VB.Bcolor;
  538.       VB.Index = VB.Bindex;
  539.    }
  540.    else {
  541.       /* use front color or index */
  542.       VB.Color = VB.Fcolor;
  543.       VB.Index = VB.Findex;
  544.    }
  545.  
  546.    (*CC.PolygonFunc)( n, vlist, provoking_vertex );
  547. }
  548.  
  549.  
  550.  
  551.  
  552. /*
  553.  * Render an un-clipped triangle.
  554.  */
  555. static void render_triangle( GLuint v0, GLuint v1, GLuint v2, GLuint pv,
  556.                              GLuint odd_flag )
  557. {
  558.    GLuint facing;
  559.    GLuint vlist[3];
  560.  
  561.    /* Compute the plane equation of polygon: ax + by + cz = d */
  562.    if (CC.ComputePlane) {
  563.       GLfloat ex = VB.Win[v1][0] - VB.Win[v0][0];
  564.       GLfloat ey = VB.Win[v1][1] - VB.Win[v0][1];
  565.       GLfloat ez = VB.Win[v1][2] - VB.Win[v0][2];
  566.       GLfloat fx = VB.Win[v2][0] - VB.Win[v0][0];
  567.       GLfloat fy = VB.Win[v2][1] - VB.Win[v0][1];
  568.       GLfloat fz = VB.Win[v2][2] - VB.Win[v0][2];
  569.       GLfloat a, b, c, d;
  570.       c = ex*fy-ey*fx;
  571.       if (c==0.0F) {
  572.      /* polygon is perpindicular to view plane, don't draw it */
  573.      return;
  574.       }
  575.  
  576.       /* compute orientation:  0=front, 1=back */
  577.       facing = (c<0.0F) ^ odd_flag ^ (CC.Polygon.FrontFace==GL_CW);
  578.  
  579.       if (CC.Polygon.CullFlag && facing==(CC.Polygon.CullFaceMode==GL_BACK)) {
  580.      return;   /* culled */
  581.       }
  582.       a = ey*fz-ez*fy;
  583.       b = ez*fx-ex*fz;
  584.       d = a*VB.Win[v0][0] + b*VB.Win[v0][1] + c*VB.Win[v0][2];
  585.       if (CC.Polygon.OffsetEnabled) {
  586.          OFFSET_POLYGON( a, b, c, d );
  587.       }
  588.       CC.PlaneA = a;
  589.       CC.PlaneB = b;
  590.       CC.PlaneC = c;
  591.       CC.PlaneD = d;
  592.    }
  593.    else {
  594.       CC.PlaneA = 0.0F;
  595.       CC.PlaneB = 0.0F;
  596.       CC.PlaneC = 1.0F;
  597.       CC.PlaneD = 0.0F;
  598.       facing = 0;
  599.    }
  600.  
  601.    if (facing==1 && CC.Light.Enabled && CC.Light.Model.TwoSide) {
  602.       /* use back color or index */
  603.       VB.Color = VB.Bcolor;
  604.       VB.Index = VB.Bindex;
  605.    }
  606.    else {
  607.       /* use front color or index */
  608.       VB.Color = VB.Fcolor;
  609.       VB.Index = VB.Findex;
  610.    }
  611.  
  612.    /* TODO: eventually call a special triangle rasterizer */
  613.    vlist[0] = v0;
  614.    vlist[1] = v1;
  615.    vlist[2] = v2;
  616.    (*CC.PolygonFunc)( 3, vlist, pv );
  617. /*
  618.    gl_smooth_rgba_triangle( v0, v1, v2, pv );
  619. */
  620. }
  621.  
  622.  
  623.  
  624.  
  625. /*
  626.  * Render an un-clipped quadrilateral.
  627.  */
  628. static void render_quad( GLuint v0, GLuint v1, GLuint v2, GLuint v3,
  629.                          GLuint pv, GLuint odd_flag )
  630. {
  631.    GLuint facing;
  632.    GLuint vlist[4];
  633.  
  634.    /* Compute the plane equation of polygon: ax + by + cz = d */
  635.    if (CC.ComputePlane) {
  636.       GLfloat ex = VB.Win[v2][0] - VB.Win[v0][0];
  637.       GLfloat ey = VB.Win[v2][1] - VB.Win[v0][1];
  638.       GLfloat ez = VB.Win[v2][2] - VB.Win[v0][2];
  639.       GLfloat fx = VB.Win[v3][0] - VB.Win[v1][0];
  640.       GLfloat fy = VB.Win[v3][1] - VB.Win[v1][1];
  641.       GLfloat fz = VB.Win[v3][2] - VB.Win[v1][2];
  642.       GLfloat a, b, c, d;
  643.       c = ex*fy-ey*fx;
  644.       if (c==0.0F) {
  645.      /* polygon is perpindicular to view plane, don't draw it */
  646.      return;
  647.       }
  648.       
  649.       /* compute orientation:  0=front, 1=back */
  650.       facing = (c<0.0F) ^ odd_flag ^ (CC.Polygon.FrontFace==GL_CW);
  651.  
  652.       if (CC.Polygon.CullFlag && facing==(CC.Polygon.CullFaceMode==GL_BACK)) {
  653.      return;   /* culled */
  654.       }
  655.       a = ey*fz-ez*fy;
  656.       b = ez*fx-ex*fz;
  657.       d = a*VB.Win[v0][0] + b*VB.Win[v0][1] + c*VB.Win[v0][2];
  658.       if (CC.Polygon.OffsetEnabled) {
  659.          OFFSET_POLYGON( a, b, c, d );
  660.       }
  661.       CC.PlaneA = a;
  662.       CC.PlaneB = b;
  663.       CC.PlaneC = c;
  664.       CC.PlaneD = d;
  665.    }
  666.    else {
  667.       CC.PlaneA = 0.0F;
  668.       CC.PlaneB = 0.0F;
  669.       CC.PlaneC = 1.0F;
  670.       CC.PlaneD = 0.0F;
  671.       facing = 0;
  672.    }
  673.  
  674.    if (facing==1 && CC.Light.Enabled && CC.Light.Model.TwoSide) {
  675.       /* use back color or index */
  676.       VB.Color = VB.Bcolor;
  677.       VB.Index = VB.Bindex;
  678.    }
  679.    else {
  680.       /* use front color or index */
  681.       VB.Color = VB.Fcolor;
  682.       VB.Index = VB.Findex;
  683.    }
  684.  
  685.    /* TODO: eventually call a triangle rasterizer twice */
  686.    vlist[0] = v0;
  687.    vlist[1] = v1;
  688.    vlist[2] = v2;
  689.    vlist[3] = v3;
  690.    (*CC.PolygonFunc)( 4, vlist, pv );
  691. }
  692.  
  693.  
  694.  
  695. /*
  696.  * When the vertex buffer is full, we transform/render it.  Sometimes we
  697.  * have to copy the last vertex (or two) to the front of the vertex list
  698.  * to "continue" the primitive.  For example:  line or triangle strips.
  699.  * This function is a helper for that.
  700.  */
  701. static void copy_vertex( GLuint dst, GLuint src )
  702. {
  703.    COPY_3V( VB.Win[dst], VB.Win[src] );
  704.    COPY_4V( VB.Eye[dst], VB.Eye[src] );
  705.    COPY_4V( VB.Fcolor[dst], VB.Fcolor[src] );
  706.    COPY_4V( VB.Bcolor[dst], VB.Bcolor[src] );
  707.    VB.Findex[dst] = VB.Findex[src];
  708.    VB.Bindex[dst] = VB.Bindex[src];
  709.    VB.Edgeflag[dst] = VB.Edgeflag[src];
  710.    COPY_4V( VB.TexCoord[dst], VB.TexCoord[src] );
  711. }
  712.  
  713.  
  714.  
  715.  
  716. /*
  717.  * Either the vertex buffer is full (VB.Count==VB_MAX) or glEnd() has been
  718.  * called.  Render the primitives defined by the vertices and reset the
  719.  * buffer.
  720.  * Input:  alldone - GL_TRUE = caller is glEnd()
  721.  *                   GL_FALSE = calling because buffer is full.
  722.  */
  723. static void render_vb( GLboolean alldone )
  724. {
  725.    GLuint vlist[VB_MAX];
  726.  
  727.    switch (CC.Mode) {
  728.       case GL_POINTS:
  729.          (*CC.PointsFunc)( 0, VB.Count-1 );
  730.      VB.Count = 0;
  731.      break;
  732.  
  733.       case GL_LINES:
  734.          if (VB.AnyClipped) {
  735.             GLuint i;
  736.             for (i=1;i<VB.Count;i+=2) {
  737.                if (VB.Unclipped[i-1] & VB.Unclipped[i]) {
  738.                   (*CC.LineFunc)( i-1, i, i );
  739.                }
  740.                else {
  741.                   render_clipped_line( i-1, i );
  742.                }
  743.                CC.StippleCounter = 0;
  744.             }
  745.          }
  746.          else {
  747.             GLuint i;
  748.             for (i=1;i<VB.Count;i+=2) {
  749.                (*CC.LineFunc)( i-1, i, i );
  750.                CC.StippleCounter = 0;
  751.             }
  752.          }
  753.      VB.Count = 0;
  754.      break;
  755.  
  756.       case GL_LINE_STRIP:
  757.      if (VB.Count>1) {
  758.             GLuint i;
  759.         for (i=1;i<VB.Count;i++) {
  760.                if (VB.Unclipped[i-1] & VB.Unclipped[i]) {
  761.                   (*CC.LineFunc)( i-1, i, i );
  762.                }
  763.                else {
  764.                   render_clipped_line( i-1, i );
  765.                }
  766.         }
  767.         if (VB.Count==VB_MAX) {
  768.                copy_vertex( 0, VB_MAX-1 );  /* copy last vertex to front */
  769.         }
  770.      }
  771.      VB.Count = 1;
  772.          break;
  773.  
  774.       case GL_LINE_LOOP:
  775.          {
  776.             GLuint i;
  777.             if (VB.Start==0) {
  778.                i = 1;  /* start at 0th vertex */
  779.             }
  780.             else {
  781.                i = 2;  /* skip first vertex, we're saving it until glEnd */
  782.             }
  783.             while (i<VB.Count) {
  784.                if (VB.Unclipped[i-1] & VB.Unclipped[i]) {
  785.                   (*CC.LineFunc)( i-1, i, i );
  786.                }
  787.                else {
  788.                   render_clipped_line( i-1, i );
  789.                }
  790.                i++;
  791.             }
  792.          }
  793.      if (alldone) {
  794.             if (VB.Unclipped[VB.Count-1] & VB.Unclipped[0]) {
  795.                (*CC.LineFunc)( VB.Count-1, 0, 0 );
  796.             }
  797.             else {
  798.                render_clipped_line( VB.Count-1, 0 );
  799.             }
  800.      }
  801.      else {
  802.         ASSERT(VB.Count==VB_MAX);
  803.         /* recycle the vertex list */
  804.             copy_vertex( 1, VB_MAX-1 );
  805.         VB.Count = 2;
  806.      }
  807.          break;
  808.  
  809.       case GL_TRIANGLES:
  810.          {
  811.             GLuint i;
  812.             for (i=2;i<VB.Count;i+=3) {
  813.                if (VB.Unclipped[i-2] & VB.Unclipped[i-1] & VB.Unclipped[i]) {
  814.                   render_triangle( i-2, i-1, i, i, 0 );
  815.                }
  816.                else {
  817.                   vlist[0] = i-2;
  818.                   vlist[1] = i-1;
  819.                   vlist[2] = i-0;
  820.                   render_clipped_polygon( 3, vlist, 0 );
  821.                }
  822.             }
  823.          }
  824.      VB.Count = 0;
  825.      break;
  826.  
  827.       case GL_TRIANGLE_STRIP:
  828.          if (VB.AnyClipped) {
  829.             GLuint i;
  830.             for (i=2;i<VB.Count;i++) {
  831.                if (VB.Unclipped[i-2] & VB.Unclipped[i-1] & VB.Unclipped[i]) {
  832.                   render_triangle( i-2, i-1, i, i, i&1 );
  833.                }
  834.                else {
  835.                   vlist[0] = i-2;
  836.                   vlist[1] = i-1;
  837.                   vlist[2] = i-0;
  838.                   render_clipped_polygon( 3, vlist, i&1 );
  839.                }
  840.             }
  841.             /* TODO: VB.AnyClipped might fail next time */
  842.          }
  843.          else {
  844.             GLuint i;
  845.             for (i=2;i<VB.Count;i++) {
  846.                render_triangle( i-2, i-1, i, i, i&1 );
  847.             }
  848.          }
  849.          if (!alldone) {
  850.             /* get ready for more vertices in this triangle strip */
  851.             copy_vertex( 0, VB_MAX-2 );
  852.             copy_vertex( 1, VB_MAX-1 );
  853.             VB.Count = 2;
  854.          }
  855.      break;
  856.  
  857.       case GL_TRIANGLE_FAN:
  858.          {
  859.             GLuint i;
  860.             for (i=2;i<VB.Count;i++) {
  861.                if (VB.Unclipped[0] & VB.Unclipped[i-1] & VB.Unclipped[i]) {
  862.                   render_triangle( 0, i-1, i, i, 0 );
  863.                }
  864.                else {
  865.                   vlist[0] = 0;
  866.                   vlist[1] = i-1;
  867.                   vlist[2] = i;
  868.                   render_clipped_polygon( 3, vlist, 0 );
  869.                }
  870.             }
  871.          }
  872.          if (!alldone) {
  873.             /* get ready for more vertices in this triangle fan */
  874.             copy_vertex( 1, VB_MAX-1 );
  875.             VB.Count = 2;
  876.      }
  877.      break;
  878.  
  879.       case GL_QUADS:
  880.          if (VB.AnyClipped) {
  881.             GLuint i;
  882.             for (i=3;i<VB.Count;i+=4) {
  883.                if (  VB.Unclipped[i-3] & VB.Unclipped[i-2]
  884.                    & VB.Unclipped[i-1] & VB.Unclipped[i]) {
  885.                   render_quad( i-3, i-2, i-1, i, i, 0 );
  886.                }
  887.                else {
  888.                   vlist[0] = i-3;
  889.                   vlist[1] = i-2;
  890.                   vlist[2] = i-1;
  891.                   vlist[3] = i-0;
  892.                   render_clipped_polygon( 4, vlist, 0 );
  893.                }
  894.             }
  895.          }
  896.          else {
  897.             GLuint i;
  898.             for (i=3;i<VB.Count;i+=4) {
  899.                render_quad( i-3, i-2, i-1, i, i, 0 );
  900.             }
  901.          }
  902.      VB.Count = 0;
  903.      break;
  904.  
  905.       case GL_QUAD_STRIP:
  906.          {
  907.             GLuint i;
  908.             for (i=3;i<VB.Count;i+=2) {
  909.                if (  VB.Unclipped[i-2] & VB.Unclipped[i-3]
  910.                    & VB.Unclipped[i-1] & VB.Unclipped[i]) {
  911.                   render_quad( i-2, i-3, i-1, i, i, 1 );
  912.                }
  913.                else {
  914.                   vlist[0] = i-2;
  915.                   vlist[1] = i-3;
  916.                   vlist[2] = i-1;
  917.                   vlist[3] = i-0;
  918.                   render_clipped_polygon( 4, vlist, 1 );
  919.                }
  920.             }
  921.          }
  922.          if (!alldone) {
  923.             /* get ready for more vertices in this quad strip */
  924.             copy_vertex( 0, VB_MAX-2 );
  925.             copy_vertex( 1, VB_MAX-1 );
  926.             VB.Count = 2;
  927.          }
  928.      break;
  929.  
  930.       case GL_POLYGON:
  931.          {
  932.             GLuint i;
  933.             for (i=0;i<VB.Count;i++) {
  934.                vlist[i] = i;
  935.             }
  936.             if (VB.AnyClipped) {
  937.                render_clipped_polygon( VB.Count, vlist, 0 );
  938.             }
  939.             else {
  940.                render_polygon( VB.Count, vlist, 0 );
  941.             }
  942.          }
  943.      if (!alldone) {
  944.             /* get ready for more vertices just like a triangle fan */
  945.             copy_vertex( 1, VB_MAX-1 );
  946.             VB.Count = 2;
  947.      }
  948.      break;
  949.  
  950.       default:
  951.          /* should never get here */
  952.      abort();
  953.    }
  954.  
  955.    /* Start = first vertex which hasn't been transformed yet */
  956.    VB.Start = VB.Count;
  957. }
  958.  
  959.  
  960.  
  961. /*
  962.  * When the Vertex Buffer is full, this function transforms all the
  963.  * vertices, normals, computes lighting, clipflags, fog, texture coords, etc.
  964.  * The hope is to maximize floating point performance inside the loops.
  965.  */
  966. static void xform_vb( GLboolean alldone )
  967. {
  968.    ASSERT( VB.Count>0 );
  969.  
  970.    /* Transform vertexes from object to eye coords */
  971.    gl_transform_points( VB.Count-VB.Start, VB.Eye+VB.Start,
  972.                         CC.ModelViewMatrix, VB.Obj+VB.Start );
  973.       
  974.    /* Transform normals from object to eye coords */
  975.    if (CC.NeedNormals) {
  976.       gl_transform_normals( VB.Count-VB.Start,
  977.                             VB.Normal+VB.Start, CC.ModelViewInv,
  978.                             VB.Normal+VB.Start, CC.Transform.Normalize );
  979.    }
  980.  
  981.    /* Lighting */
  982.    if (CC.Light.Enabled) {
  983.       if (CC.RGBAflag) {
  984.          if (VB.MaterialChanges) {
  985.             GLuint i;
  986.             /* NOTE the <= here.  This is needed in case glColor/glMaterial
  987.              * is called after the last glVertex inside a glBegin/glEnd pair.
  988.              */
  989.         for (i=VB.Start;i<=VB.Count;i++) {
  990.                update_material( i );
  991.            gl_color_shade( VB.Eye[i], VB.Normal[i], CC.LightTwoSide,
  992.                    VB.Fcolor[i], VB.Bcolor[i] );
  993.         }
  994.      }
  995.          else {
  996.             gl_color_shade_vertices( VB.Count-VB.Start,
  997.                                      VB.Eye + VB.Start,
  998.                                      VB.Normal + VB.Start,
  999.                                      CC.LightTwoSide,
  1000.                                      VB.Fcolor + VB.Start,
  1001.                                      VB.Bcolor + VB.Start );
  1002.      }
  1003.       }
  1004.       else {
  1005.          if (VB.MaterialChanges) {
  1006.             GLuint i;
  1007.             /* NOTE the <= here.  This is needed in case glColor/glMaterial
  1008.              * is called after the last glVertex inside a glBegin/glEnd pair.
  1009.              */
  1010.             for (i=VB.Start;i<=VB.Count;i++) {
  1011.                update_material( i );
  1012.                gl_index_shade( VB.Eye[i], VB.Normal[i], CC.LightTwoSide,
  1013.                                &VB.Findex[i], &VB.Bindex[i] );
  1014.             }
  1015.          }
  1016.          else {
  1017.             GLuint i;
  1018.             for (i=VB.Start;i<VB.Count;i++) {
  1019.                gl_index_shade( VB.Eye[i], VB.Normal[i], CC.LightTwoSide,
  1020.                                &VB.Findex[i], &VB.Bindex[i] );
  1021.             }
  1022.          }
  1023.       }
  1024.    }
  1025.  
  1026.    /* Per-vertex fog */
  1027.    if (CC.Fog.Enabled && CC.Hint.Fog!=GL_NICEST) {
  1028.       if (CC.RGBAflag) {
  1029.          /* Fog RGB colors */
  1030.          gl_fog_color_vertices( VB.Count - VB.Start,
  1031.                                 VB.Eye + VB.Start,
  1032.                                 VB.Fcolor + VB.Start );
  1033.          if (CC.LightTwoSide) {
  1034.             gl_fog_color_vertices( VB.Count - VB.Start,
  1035.                                    VB.Eye + VB.Start,
  1036.                                    VB.Bcolor + VB.Start );
  1037.          }
  1038.       }
  1039.       else {
  1040.          /* Fog color indexes */
  1041.          gl_fog_index_vertices( VB.Count - VB.Start,
  1042.                                 VB.Eye + VB.Start,
  1043.                                 VB.Findex + VB.Start );
  1044.          if (CC.LightTwoSide) {
  1045.             gl_fog_index_vertices( VB.Count - VB.Start,
  1046.                                    VB.Eye + VB.Start,
  1047.                                    VB.Bindex + VB.Start );
  1048.          }
  1049.       }
  1050.    }
  1051.  
  1052.    /* Compute/transform texture coords */
  1053.    if (CC.Texture.Enabled) {
  1054.       GLuint i;
  1055.       for (i=VB.Start;i<VB.Count;i++) {
  1056.          if (CC.Texture.TexGenEnabled) {
  1057.             gl_do_texgen( VB.Obj[i], VB.Eye[i], VB.Normal[i], VB.TexCoord[i] );
  1058.          }
  1059.          if (!CC.IdentityTexMat) {
  1060.             /* transform current texture coordinate by texture matrix */
  1061.             /* tc = TexMat * TexCoord */
  1062.             GLfloat tc[4];
  1063.             TRANSFORM_POINT( tc, CC.TextureMatrix, VB.TexCoord[i] );
  1064.             COPY_4V( VB.TexCoord[i], tc );
  1065.          }
  1066.       }
  1067.    }
  1068.  
  1069.    if (CC.Transform.AnyClip) {
  1070.       /* Clip against user-defined clip planes */
  1071.       GLuint p;
  1072.       VB.AnyClipped = GL_FALSE;
  1073.       for (p=0;p<MAX_CLIP_PLANES;p++) {
  1074.          if (CC.Transform.ClipEnabled[p]) {
  1075.             GLuint i;
  1076.             GLfloat a = CC.Transform.ClipEquation[p][0];
  1077.             GLfloat b = CC.Transform.ClipEquation[p][1];
  1078.             GLfloat c = CC.Transform.ClipEquation[p][2];
  1079.             GLfloat d = CC.Transform.ClipEquation[p][3];
  1080.             for (i=VB.Start;i<VB.Count;i++) {
  1081.                GLfloat dot = VB.Eye[i][0] * a + VB.Eye[i][1] * b
  1082.                            + VB.Eye[i][2] * c + VB.Eye[i][3] * d;
  1083.                if (dot < 0.0F) {
  1084.                   VB.Unclipped[i] = GL_FALSE;
  1085.                   VB.AnyClipped = GL_TRUE;
  1086.                }
  1087.                else {
  1088.                   VB.Unclipped[i] = GL_TRUE;
  1089.                }
  1090.             }
  1091.          }
  1092.       }
  1093.    }
  1094.    else {
  1095.       /* Initialize clip flags */
  1096.       MEMSET( VB.Unclipped+VB.Start, 1, VB.Count-VB.Start );
  1097.       VB.AnyClipped = GL_FALSE;
  1098.    }
  1099.  
  1100.    /* Transform vertices from eye to clip coords */
  1101.    /* Even transform clipped vertices because it's usually faster. */
  1102.    gl_transform_points( VB.Count-VB.Start, VB.Clip+VB.Start,
  1103.                         CC.ProjectionMatrix, VB.Eye+VB.Start );
  1104.  
  1105.    /* Clip vertices against view volume */
  1106.    {
  1107.       GLuint i;
  1108.       for (i=VB.Start;i<VB.Count;i++) {
  1109.          /* Unclipped[i] will remain TRUE if vertex is inside view volume */
  1110.          if (VB.Clip[i][0] > VB.Clip[i][3] || VB.Clip[i][0] < -VB.Clip[i][3] ||
  1111.              VB.Clip[i][1] > VB.Clip[i][3] || VB.Clip[i][1] < -VB.Clip[i][3] ||
  1112.              VB.Clip[i][2] > VB.Clip[i][3] || VB.Clip[i][2] < -VB.Clip[i][3] ){
  1113.             VB.Unclipped[i] = GL_FALSE;
  1114.             VB.AnyClipped = GL_TRUE;
  1115.          }
  1116.       }
  1117.    }
  1118.       
  1119.    /* Map vertices from clip to window coords */
  1120.    if (VB.AnyClipped) {
  1121.       GLuint i;
  1122.       GLfloat sx = CC.Viewport.Sx,  tx = CC.Viewport.Tx;
  1123.       GLfloat sy = CC.Viewport.Sy,  ty = CC.Viewport.Ty;
  1124.       GLfloat sz = CC.Viewport.Sz,  tz = CC.Viewport.Tz;
  1125.       for (i=VB.Start;i<VB.Count;i++) {
  1126.          if (VB.Unclipped[i]) {
  1127.             GLfloat d;
  1128.             ASSERT( VB.Clip[i][3] != 0.0 );
  1129.             d = 1.0F / VB.Clip[i][3];
  1130.             VB.Win[i][0] = VB.Clip[i][0] * d * sx + tx;
  1131.             VB.Win[i][1] = VB.Clip[i][1] * d * sy + ty;
  1132.             VB.Win[i][2] = VB.Clip[i][2] * d * sz + tz;
  1133.          }
  1134.       }
  1135.    }
  1136.    else {
  1137.       /* This is written to unroll with IRIX 5.3 cc */
  1138.       GLuint i = VB.Start, n = VB.Count;
  1139.       GLfloat sx = CC.Viewport.Sx,  tx = CC.Viewport.Tx;
  1140.       GLfloat sy = CC.Viewport.Sy,  ty = CC.Viewport.Ty;
  1141.       GLfloat sz = CC.Viewport.Sz,  tz = CC.Viewport.Tz;
  1142.       while (i!=n) {
  1143.          GLfloat d = 1.0F / VB.Clip[i][3];
  1144.          ASSERT( VB.Clip[i][3] != 0.0 );
  1145.          VB.Win[i][0] = VB.Clip[i][0] * d * sx + tx;
  1146.          VB.Win[i][1] = VB.Clip[i][1] * d * sy + ty;
  1147.          VB.Win[i][2] = VB.Clip[i][2] * d * sz + tz;
  1148.          i++;
  1149.       }
  1150.    }
  1151.  
  1152.    /* Render the primitives */
  1153.    render_vb( alldone );
  1154. }
  1155.  
  1156.  
  1157.  
  1158. /*
  1159.  * Copy the vertex and associated data into the VB.  When the VB is
  1160.  * full, render the primitives.
  1161.  */
  1162. void gl_execute_vertex( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1163. {
  1164.    ASSIGN_4V( VB.Obj[VB.Count], x, y, z, w );
  1165.    if (CC.Light.Enabled) {
  1166.       COPY_3V( VB.Normal[VB.Count], CC.Current.Normal );
  1167.    }
  1168.    if (CC.RGBAflag) {
  1169.       COPY_4V( VB.Fcolor[VB.Count], CC.Current.Color );
  1170.       if (CC.Texture.Enabled) {
  1171.          COPY_4V( VB.TexCoord[VB.Count], CC.Current.TexCoord );
  1172.       }
  1173.    }
  1174.    else {
  1175.       VB.Findex[VB.Count] = (GLfloat) CC.Current.Index;
  1176.    }
  1177.    VB.Edgeflag[VB.Count] = CC.Current.EdgeFlag;
  1178.  
  1179.    VB.Count++;
  1180.    if (VB.Count==VB_MAX) {
  1181.       xform_vb( GL_FALSE );
  1182.    }
  1183. }
  1184.  
  1185.  
  1186. /*
  1187.  * Save a glVertex call into a display list AND execute it.
  1188.  */
  1189. void gl_save_and_execute_vertex( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1190. {
  1191.    gl_save_vertex( x, y, z, w );
  1192.    gl_execute_vertex( x, y, z, w );
  1193. }
  1194.  
  1195.  
  1196.  
  1197.  
  1198. /*
  1199.  * Process a vertex produced by an evaluator.
  1200.  * Input:  v - vertex
  1201.  *         n - normal
  1202.  *         c - color
  1203.  *         i - color index
  1204.  *         t - texture coordinate
  1205.  */
  1206. void gl_eval_vertex( const GLfloat v[4], const GLfloat n[3],
  1207.              const GLfloat c[4], GLfloat i, GLfloat t[4] )
  1208. {
  1209.    COPY_4V( VB.Obj[VB.Count], v );
  1210.    COPY_3V( VB.Normal[VB.Count], n );
  1211.    COPY_4V( VB.Fcolor[VB.Count], c );
  1212.    VB.Findex[VB.Count] = i;
  1213.    COPY_4V( VB.TexCoord[VB.Count], t );
  1214.    VB.Edgeflag[VB.Count] = CC.Current.EdgeFlag;
  1215.  
  1216.    VB.Count++;
  1217.    if (VB.Count==VB_MAX) {
  1218.       xform_vb( GL_FALSE );
  1219.    }
  1220. }
  1221.  
  1222.  
  1223.  
  1224.  
  1225. void gl_rasterpos( const GLfloat v[4] )
  1226. {
  1227.    GLfloat eye[4], clip[4], ndc[3], d;
  1228.  
  1229.    /* transform v to eye coords:  eye = ModelView * v */
  1230.    TRANSFORM_POINT( eye, CC.ModelViewMatrix, v );
  1231.  
  1232.    /* compute lighting */
  1233.    if (CC.Light.Enabled) {
  1234.       GLfloat eyenorm[3];
  1235.       if (!CC.ModelViewInvValid) {
  1236.      gl_compute_modelview_inverse();
  1237.       }
  1238.       TRANSFORM_NORMAL( eyenorm[0], eyenorm[1], eyenorm[2], CC.Current.Normal,
  1239.                         CC.ModelViewInv );
  1240.       if (CC.RGBAflag) {
  1241.      gl_color_shade( eye, eyenorm, 0, CC.Current.RasterColor, NULL );
  1242.       }
  1243.       else {
  1244.      GLfloat indx;
  1245.      gl_index_shade( eye, eyenorm, 0, &indx, NULL );
  1246.      CC.Current.RasterIndex = (GLuint) (GLint) indx;
  1247.       }
  1248.    }
  1249.    else {
  1250.       /* copy current color or index */
  1251.       if (CC.RGBAflag) {
  1252.      COPY_4V( CC.Current.RasterColor, CC.Current.Color );
  1253.       }
  1254.       else {
  1255.      CC.Current.RasterIndex = CC.Current.Index;
  1256.       }
  1257.    }
  1258.  
  1259.    /* clip to user clipping planes */
  1260.    if (gl_userclip_point(eye)==0) {
  1261.       CC.Current.RasterPosValid = GL_FALSE;
  1262.       return;
  1263.    }
  1264.  
  1265.    /* compute raster distance */
  1266.    CC.Current.RasterDistance = (GLfloat)
  1267.                       sqrt( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );
  1268.  
  1269.    /* apply projection matrix:  clip = Proj * eye */
  1270.    TRANSFORM_POINT( clip, CC.ProjectionMatrix, eye );
  1271.  
  1272.    /* clip to view volume */
  1273.    if (gl_viewclip_point( clip )==0) {
  1274.       CC.Current.RasterPosValid = GL_FALSE;
  1275.       return;
  1276.    }
  1277.  
  1278.    /* ndc = clip / W */
  1279.    ASSERT( clip[3]!=0.0 );
  1280.    d = 1.0F / clip[3];
  1281.    ndc[0] = clip[0] * d;
  1282.    ndc[1] = clip[1] * d;
  1283.    ndc[2] = clip[2] * d;
  1284.  
  1285.    CC.Current.RasterPos[0] = MAP_X( ndc[0] );
  1286.    CC.Current.RasterPos[1] = MAP_Y( ndc[1] );
  1287.    CC.Current.RasterPos[2] = MAP_Z( ndc[2] );
  1288.    CC.Current.RasterPos[3] = clip[3];
  1289.    CC.Current.RasterPosValid = GL_TRUE;
  1290.  
  1291.    /* FOG??? */
  1292.  
  1293.    if (CC.Texture.Enabled) {
  1294.       /* TODO: Current.RasterTexCoord */
  1295.  
  1296.    }
  1297.  
  1298.    if (CC.RenderMode==GL_SELECT) {
  1299.       /* TODO: is this correct? */
  1300.       CC.HitFlag = GL_TRUE;
  1301.       if (CC.Current.RasterPos[2] < CC.HitMinZ) {
  1302.      CC.HitMinZ = CC.Current.RasterPos[2];
  1303.       }
  1304.       if (CC.Current.RasterPos[2] < CC.HitMaxZ) {
  1305.      CC.HitMaxZ = CC.Current.RasterPos[2];
  1306.       }
  1307.    }
  1308.  
  1309. }
  1310.  
  1311.  
  1312.  
  1313. void gl_index( GLuint index )
  1314. {
  1315.    /* TODO: inline this assignment! */
  1316.    CC.Current.Index = index;
  1317.    VB.MonoColor = GL_FALSE;
  1318. }
  1319.  
  1320.  
  1321.  
  1322. void gl_color( const GLfloat color[4] )
  1323. {
  1324.    /* TODO: inline this assignment! */
  1325.    COPY_4V( CC.Current.Color, color );
  1326.    if (CC.Light.Enabled && CC.Light.ColorMaterialEnabled) {
  1327.       /* Translate this glColor() call into a glMaterial() call */
  1328.       gl_material( CC.Light.ColorMaterialFace,
  1329.                    CC.Light.ColorMaterialMode, color );
  1330.    }
  1331.    VB.MonoColor = GL_FALSE;
  1332. }
  1333.  
  1334.  
  1335.  
  1336. void gl_begin( GLenum p )
  1337. {
  1338.    CC.Mode = p;
  1339.    VB.Start = VB.Count = 0;
  1340.  
  1341.    if (!CC.ModelViewInvValid) {
  1342.       gl_compute_modelview_inverse();
  1343.    }
  1344.    if (CC.NewState) {
  1345.       gl_update_state();
  1346.    }
  1347.  
  1348.    VB.MonoColor = !CC.Light.Enabled && !CC.Texture.Enabled
  1349.                 && !CC.Color.BlendEnabled && !CC.Color.SWLogicOpEnabled;
  1350.    if (VB.MonoColor) {
  1351.       if (CC.RGBAflag) {
  1352.          GLubyte r = (GLint) (CC.Current.Color[0] * CC.RedScale);
  1353.          GLubyte g = (GLint) (CC.Current.Color[1] * CC.GreenScale);
  1354.          GLubyte b = (GLint) (CC.Current.Color[2] * CC.BlueScale);
  1355.          GLubyte a = (GLint) (CC.Current.Color[3] * CC.AlphaScale);
  1356.          if (CC.RasterMask & GAMMA_BIT) {
  1357.             gl_apply_gamma( 1, &r, &g, &b );
  1358.          }
  1359.          (*DD.color)( r, g, b, a );
  1360.       }
  1361.       else {
  1362.          (*DD.index)(CC.Current.Index);
  1363.       }
  1364.    }
  1365.  
  1366.    switch (CC.Mode) {
  1367.       case GL_POINTS:
  1368.      CC.LightTwoSide = 0;
  1369.      VB.Color = VB.Fcolor;
  1370.      VB.Index = VB.Findex;
  1371.      gl_init_pb( GL_POINT );
  1372.      break;
  1373.       case GL_LINES:
  1374.       case GL_LINE_STRIP:
  1375.       case GL_LINE_LOOP:
  1376.      CC.LightTwoSide = 0;
  1377.      VB.Color = VB.Fcolor;
  1378.      VB.Index = VB.Findex;
  1379.      CC.StippleCounter = 0;
  1380.      gl_init_pb( GL_LINE );
  1381.          break;
  1382.       case GL_TRIANGLES:
  1383.       case GL_TRIANGLE_STRIP:
  1384.       case GL_TRIANGLE_FAN:
  1385.       case GL_QUADS:
  1386.       case GL_QUAD_STRIP:
  1387.       case GL_POLYGON:
  1388.      CC.LightTwoSide = (GLuint) CC.Light.Model.TwoSide;
  1389.      gl_init_pb( GL_POLYGON );
  1390.          break;
  1391.       default:
  1392.      gl_error( GL_INVALID_ENUM, "glBegin" );
  1393.      CC.Mode = GL_BITMAP;
  1394.    }
  1395. }
  1396.  
  1397.  
  1398.  
  1399. void gl_end( void )
  1400. {
  1401.    if (CC.Mode==GL_BITMAP) {
  1402.       /* glEnd without glBegin */
  1403.       gl_error( GL_INVALID_OPERATION, "glEnd" );
  1404.       return;
  1405.    }
  1406.  
  1407.    if (VB.Count>VB.Start) {
  1408.       xform_vb( GL_TRUE );
  1409.    }
  1410.    if (PB.count>0) {
  1411.       gl_flush_pb();
  1412.    }
  1413.    PB.primitive = CC.Mode = GL_BITMAP;  /* Default mode */
  1414.    VB.MaterialChanges = GL_FALSE;
  1415. }
  1416.  
  1417.  
  1418.  
  1419.  
  1420. /*
  1421.  *
  1422.  * Public functions
  1423.  *
  1424.  */
  1425.  
  1426. void glBegin( GLenum p )
  1427. {
  1428.    if (CC.CompileFlag) {
  1429.       gl_save_begin( p );
  1430.    }
  1431.    if (CC.ExecuteFlag) {
  1432.       gl_begin( p );
  1433.    }
  1434. }
  1435.  
  1436.  
  1437.  
  1438. void glEnd( void )
  1439. {
  1440.    if (CC.CompileFlag) {
  1441.       gl_save_end();
  1442.    }
  1443.    if (CC.ExecuteFlag) {
  1444.       gl_end();
  1445.    }
  1446. }
  1447.